package Parser;


public class Token{
    public static final int TR = 1;
    public static final int TD = 2;
    public static final int IMG = 3;
    public static final int DIV = 4;
    public static final int P = 5;
    public static final int BR = 6;
    public static final int OTHER = 7;
    public static final int TEXT = 8;
    public static final int FONT = 9;
    public static final int B = 10;
    public static final int I = 11;
    public static final int H1 = 12;
    public static final int H2 = 13;
    public static final int H3 = 14;
    public static final int H4 = 15;
    public static final int LI = 16;
    public static final int UL = 17;
    public static final int TH = 18;
    public static final int TABLE = 19;
    public static final int BLOCKQUOTE = 20;
    public static final int CENTER = 21;
    public static final int BODY = 22;
    public static final int A = 23;
    public static final int SPAN = 24;
    public static final int SCRIPT = 25;
    public static final int HTML = 26;
    public static final int IFRAME = 27;
    public static final int TITLE = 28;
    public static final int STYLE = 29;
    public static final int MAP = 30;
    public static final int CLOSE_MAP = -30;
    public static final int CLOSE_STYLE = -29;
    public static final int CLOSE_TITLE = -28;
    public static final int COMMENT = 100;
    public static final int CLOSE_IFRAME = -27;
    public static final int CLOSE_BLOCKQUOTE = -20;
    public static final int CLOSE_TABLE = -19;
    public static final int CLOSE_TR = -1;
    public static final int CLOSE_TD = -2;
    public static final int CLOSE_IMG = -3;
    public static final int CLOSE_DIV = -4;
    public static final int CLOSE_P = -5;
    public static final int CLOSE_BR = -6;
    public static final int CLOSE_OTHER = -7;
    public static final int CLOSE_TH = -18;
    public static final int CLOSE_UL = -17;
    public static final int CLOSE_LI = -16;
    public static final int CLOSE_H1 = -12;
    public static final int CLOSE_H2 = -13;
    public static final int CLOSE_H3 = -14;
    public static final int CLOSE_H4 = -15;
    public static final int CLOSE_I = -11;
    public static final int CLOSE_BODY = -22;
    public static final int CLOSE_CENTER = -21;
    public static final int CLOSE_B = -10;
    public static final int CLOSE_FONT = -9;
    public static final int CLOSE_A = -23;
    public static final int CLOSE_SPAN = -24;
    public static final int CLOSE_SCRIPT = -25;
    public static final int CLOSE_HTML = -26;

    public static final int NUM_TOKEN_TYPES = 23;

    private String token;
    private boolean isTag;
    private int type;

    public boolean hasClose()
    {
        if (type == TR || type == TD || type == TH || type == DIV ||
        type == UL || type == LI || type == I || type == B || type == CENTER ||
        type == FONT || type == A || type == H1 || type == H2 || type == H3
        || type == H4 || type == TABLE || type == BLOCKQUOTE || type == SPAN || type == SCRIPT || type == HTML
        || type == IFRAME || type == TITLE || type == STYLE || type == MAP)
        return true;
        else
          return false;
    }

    public boolean closes(Token t)
    {
        if (t.getType() * -1 == type)
          return true;
        else
          return false;
    }

    public Token generateClose()
    {
        Token result = null;

        if (isClose())
            throw new RuntimeException("Trying to produce a close for a close token");

        if (type == TEXT)
            throw new RuntimeException("Trying to close a text token");

        if (type == OTHER)
            throw new RuntimeException("Trying to close an unknown (OTHER) token type");

        switch (type)
        {
        case TR:
            result = new Token("</tr>");
            break;
        case TD:
            result = new Token("</td>");
            break;
        case IMG:
            result = new Token("</img>");
            break;
        case DIV:
            result = new Token("</div>");
            break;
        case P:
            result = new Token("</p>");
            break;
        case BR:
            result = new Token("</br>");
            break;
        case FONT:
            result = new Token("</font>");
            break;
        case B:
            result = new Token("</b>");
            break;
        case I:
            result = new Token("</i>");
            break;
        case H1:
            result = new Token("</h1>");
            break;
        case H2:
            result = new Token("</h1>");
            break;
        case H3:
            result = new Token("</h3>");
            break;
        case H4:
            result = new Token("</h4>");
            break;
        case LI:
            result = new Token("</li>");
            break;
        case UL:
            result = new Token("</ul>");
            break;
        case TH:
            result = new Token("</th>");
            break;
        case TABLE:
            result = new Token("</table>");
            break;
        case BLOCKQUOTE:
            result = new Token("</blockquote>");
            break;
        case CENTER:
            result = new Token("</center>");
            break;
        case BODY:
            result = new Token("</body>");
            break;
        case A:
            result = new Token("</a>");
            break;
        case SPAN:
            result = new Token("</span>");
            break;
        case SCRIPT:
            result = new Token("</script>");
            break;
        case HTML:
            result = new Token("</html>");
            break;
        case IFRAME:
            result = new Token("</iframe>");
            break;
        case TITLE:
            result = new Token("</title>");
            break;
        case STYLE:
            result = new Token("</style>");
            break;
        case MAP:
            result = new Token("</map>");
            break;
        default:
            throw new RuntimeException("Trying to close an unknown (NOT IMPLEMENTED) token type");
        }

        return result;
    }
    
    public boolean isSelfClosing() {
        if (token.length() < 2)
          return false;
        return token.charAt(token.length() - 2) == '/';
    }

    public boolean isClose()
    {
        if (type < 0)
          return true;
        else
          return false;
    }

    public String getTag() {
        if (!isTag)
            return null;

        String tag;
        int pos;

        pos = 1;
        while (pos < token.length() && token.charAt(pos) != '>' && !isWhiteSpace(token.charAt(pos))) {
            pos++;
        }

        if (pos == token.length())
            System.err.println("WTF");

        try {
        tag = token.substring(1, pos);
        } catch(Exception ex) {
            ex.printStackTrace();
            tag = null;
        }
        return tag;
    }

    public boolean isRequiredClose()
    {
        if (type == CLOSE_TR || type == CLOSE_TD || type == CLOSE_TH || type == CLOSE_DIV ||
            type == CLOSE_UL || type == CLOSE_LI || type == CLOSE_I || type == CLOSE_B || type == CLOSE_CENTER ||
            type == CLOSE_FONT || type == CLOSE_A || type == CLOSE_H1 || type == CLOSE_H2 || type == CLOSE_H3
            || type == CLOSE_H4 || type == CLOSE_TABLE || type == CLOSE_BLOCKQUOTE || type == CLOSE_SPAN
            || type == CLOSE_HTML || type == CLOSE_IFRAME || type == CLOSE_TITLE || type == CLOSE_STYLE
            || type == CLOSE_MAP)
            return true;
        else
            return false;
    }

    public String toString()
    {
        return token;
    }

    public int getType()
    {
        return type;
    }

    // Returns null if unspecified
    public String valueOfAtt(String att)
    {
        int pos;
        int pos2;
        String copy = token.toLowerCase();

        att = att.toLowerCase();

        // Find the attribute, and return its value
        pos = copy.indexOf(att);

        if (pos < 0)
          return null;

        // Find the equals sign
        pos = copy.indexOf('=', pos + 1);
        if (pos < 0)
            // No equal sign, fail
            return null;

        pos++;
        while (isWhiteSpace(copy.charAt(pos)))
                pos++;

        if (copy.charAt(pos) == '"')
        {
            // It is, go to the next one
            pos2 = copy.indexOf('"', pos + 1);
            return token.substring(pos + 1, pos2);
        }
        else if (copy.charAt(pos) == '\'') {
            pos2 = copy.indexOf('\'', pos + 1);
            return token.substring(pos + 1, pos2);
        }
        else
        {
            pos2 = pos;
            while ( !isWhiteSpace(copy.charAt(pos2)) && copy.charAt(pos2) != '>' )
            {
                pos2++;
            }
            
            if (type == Token.SPAN)
                return token.substring(pos, pos2);

            return token.substring(pos, pos2);
        }
    }

    public Token(String t) {
        token = t;
        idToken();
    }

    private void idToken() {
        String low = token.toLowerCase();

        if (token.charAt(0) == '<')
        {
            isTag = true;
        }
        else
        {
            isTag = false;
            type = TEXT;
            return;
        }

        if ( (low.length() >= 3) && low.substring(1, 3).equals("p ") ||
            (low.length() >= 3) && low.substring(1, 3).equals("p>") )
        {
            type = P;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("br ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("br>"))
        {
            type = BR;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("body ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("body>"))
        {
            type = BODY;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("span ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("span>"))
        {
            type = SPAN;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("table ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("table>"))
        {
            type = TABLE;
        }
        else if ( (low.length() >= 8) && low.substring(1, 8).equals("center ") ||
            (low.length() >= 8) && low.substring(1, 8).equals("center>"))
        {
            type = CENTER;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("tr ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("tr>"))
        {
            type = TR;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("td ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("td>"))
        {
            type = TD;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("img ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("img>"))
        {
            type = IMG;
        }
        else if ( (low.length() >= 3) && low.substring(1, 3).equals("i ") ||
            (low.length() >= 3) && low.substring(1, 3).equals("i>"))
        {
            type = I;
        }
        else if ( (low.length() >= 3) && low.substring(1, 3).equals("b ") ||
            (low.length() >= 3) && low.substring(1, 3).equals("b>"))
        {
            type = B;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("div ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("div>"))
        {
            type = DIV;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("font ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("font>"))
        {
            type = FONT;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("html ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("html>"))
        {
            type = HTML;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("h1 ") ||
             (low.length() >= 4) && low.substring(1, 4).equals("h1>"))
        {
            type = H1;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("h2 ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("h2>"))
        {
            type = H2;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("h3 ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("h3>"))
        {
            type = H3;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("h4 ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("h4>"))
        {
            type = H4;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("ul ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("ul>"))
        {
            type = UL;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("li ") ||
             (low.length() >= 4) && low.substring(1, 4).equals("li>"))
        {
            type = LI;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("th ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("th>"))
        {
            type = TH;
        }
        else if ( (low.length() >= 8) && low.substring(1, 8).equals("script ") ||
            (low.length() >= 8) && low.substring(1, 8).equals("script>"))
        {
            type = SCRIPT;
        }
        else if ((low.length() >= 13) && low.substring(1, 13).equals("blockquote ") ||
            (low.length() >= 13) && low.substring(1, 13).equals("blockquote>")) {
            type = BLOCKQUOTE;
        }
        else if ((low.length() >= 3) && low.substring(1, 3).equals("a ") ||
            (low.length() >= 3) && low.substring(1, 3).equals("a>")) {
            type = A;
        }
        else if ( (low.length() >= 8) && low.substring(1, 8).equals("iframe ") ||
            (low.length() >= 8) && low.substring(1, 8).equals("iframe>"))
        {
            type = IFRAME;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("!--") ||
            (low.length() >= 4) && low.substring(1, 4).equals("th>"))
        {
            type = COMMENT;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("title ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("title>"))
        {
            type = TITLE;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("style ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("style>"))
        {
            type = STYLE;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("map ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("map>"))
        {
            type = MAP;
        }


        else if ( (low.length() >= 4) && low.substring(1, 4).equals("/p ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("/p>"))
        {
            type = CLOSE_P;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("/body ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("/body>"))
        {
            type = CLOSE_BODY;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("/span ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("/span>"))
        {
            type = CLOSE_SPAN;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/br ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/br>"))
        {
            type = CLOSE_BR;
        }
        else if ( (low.length() >= 8) && low.substring(1, 8).equals("/table ") ||
            (low.length() >= 8) && low.substring(1, 8).equals("/table>"))
        {
            type = CLOSE_TABLE;
        }
        else if ( (low.length() >= 9) && low.substring(1, 9).equals("/center ") ||
            (low.length() >= 9) && low.substring(1, 9).equals("/center>"))
        {
            type = CLOSE_CENTER;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/tr ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/tr>"))
        {
            type = CLOSE_TR;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/td ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/td>"))
        {
            type = CLOSE_TD;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("/img ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("/img>"))
        {
            type = CLOSE_IMG;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("/b ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("/b>"))
        {
            type = CLOSE_B;
        }
        else if ( (low.length() >= 4) && low.substring(1, 4).equals("/i ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("/i>"))
        {
            type = CLOSE_I;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("/div ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("/div>"))
        {
            type = CLOSE_DIV;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("/font ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("/font>"))
        {
            type = CLOSE_FONT;
        }
        else if ( (low.length() >= 7) && low.substring(1, 7).equals("/html ") ||
            (low.length() >= 7) && low.substring(1, 7).equals("/html>"))
        {
            type = CLOSE_HTML;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/h1 ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/h1>"))
        {
            type = CLOSE_H1;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/h2 ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/h2>"))
        {
            type = CLOSE_H2;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/h3 ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/h3>"))
        {
            type = CLOSE_H3;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/h4 ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/h4>"))
        {
            type = CLOSE_H4;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/ul ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/ul>"))
        {
            type = CLOSE_UL;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/li ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/li>"))
        {
            type = CLOSE_LI;
        }
        else if ( (low.length() >= 5) && low.substring(1, 5).equals("/th ") ||
            (low.length() >= 5) && low.substring(1, 5).equals("/th>"))
        {
            type = CLOSE_TH;
        }
        else if ((low.length() >= 14) && low.substring(1, 14).equals("/blockquote ") ||
            (low.length() >= 14) && low.substring(1, 14).equals("/blockquote>")) {
            type = CLOSE_BLOCKQUOTE;
        }
        else if ((low.length() >= 4) && low.substring(1, 4).equals("/a ") ||
            (low.length() >= 4) && low.substring(1, 4).equals("/a>")) {
            type = CLOSE_A;
        }
        else if ( (low.length() >= 9) && low.substring(1, 9).equals("/script ") ||
            (low.length() >= 9) && low.substring(1, 9).equals("/script>"))
        {
            type = CLOSE_SCRIPT;
        }
        else if ( (low.length() >= 9) && low.substring(1, 9).equals("/iframe ") ||
            (low.length() >= 9) && low.substring(1, 9).equals("/iframe>"))
        {
            type = CLOSE_IFRAME;
        }
        else if ( (low.length() >= 8) && low.substring(1, 8).equals("/title ") ||
            (low.length() >= 8) && low.substring(1, 8).equals("/title>"))
        {
            type = CLOSE_TITLE;
        }
        else if ( (low.length() >= 8) && low.substring(1, 8).equals("/style ") ||
            (low.length() >= 8) && low.substring(1, 8).equals("/style>"))
        {
            type = CLOSE_STYLE;
        }
        else if ( (low.length() >= 6) && low.substring(1, 6).equals("/map ") ||
            (low.length() >= 6) && low.substring(1, 6).equals("/map>"))
        {
            type = CLOSE_STYLE;
        }




        else if ( (low.length() > 1) && low.charAt(1) == '/')
        {
            type = CLOSE_OTHER;
        }
        else
        {
            type = OTHER;
        }


    }

    public boolean isWhiteSpace(char c)
    {
        return Character.isWhitespace(c);
    }


}

